using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace FoundationLib.AddIns.Constraints.Visitors
{
	/// <summary>
	/// Represents a visitor evaluating primitive OCL statements
	/// </summary>
	public class PrimitivesVisitor : IVisitor
	{
		private const string PATTERN = @"([^@ ]+)@pre";

		/// <summary>
		/// Creates a new primitives visitor
		/// </summary>
		public PrimitivesVisitor()
		{
		}

		private string GenerateReturn(IVisitable stmt)
		{
			MethodOclStatement methodStmt = stmt as MethodOclStatement;
			if (methodStmt != null)
			{
				string format = FormatManager.GetFormat("Result");
				return String.Format(format + " ", methodStmt.ReturnTypeName, methodStmt.ReturnIsArray ? "[]" : "");
			}
			else
			{
				return "result";
			}
		}

		private string ConvertOldValue(string input)
		{
			Regex regex = new Regex(PATTERN);
			string format = FormatManager.GetFormat("OldValue");
			return regex.Replace(input, (x) => {
				return String.Format(format, x.Groups[1].Value);
			});
		}

		/// <summary>
		/// Visits the statement
		/// </summary>
		/// <param name="statement">The statement to visit</param>
		public void Visit(IVisitable statement)
		{
			if (statement == null)
				return;

			StringBuilder b = new StringBuilder(statement.Value);
			b.Replace(" and ", " && ")
				.Replace(" or ", "||")
				.Replace(" not ", "!")
				.Replace(" <> ", " != ")
				.Replace(" = ", " == ")
				.Replace("Date::now", "DateTime.Now")
				.Replace("result ", this.GenerateReturn(statement))
				.Replace("self.", "this.");

			string result = b.ToString();
			result = this.ConvertOldValue(result);

			statement.Value = result;
		}
	}
}
